<html>
  <body>
    <canvas
      id="myCanvas"
      width="600"
      height="500"
      style="position: absolute; left: 0"
    ></canvas>
    <script>
      let canvas = document.getElementById("myCanvas");
      let context = canvas.getContext("2d");
      context.font = "bold 30px sans-serif";
      context.lineWidth = 4;
      let image = new Image();
      image.src = "sprite.png";
      const maxStones = 6,
        size = 40;
      let angle = -Math.PI / 2;
      let x, y, frame, currentStone, mode, run, offset, stickLength, stones;

      function reset() {
        currentStone = 0;
        x = 100;
        y = 360;
        frame = 0;
        stones = [];
        stickLength = 0;
        offset = 0;
        run = 0;
        for (let i = 0; i < maxStones; i++) {
          stones[i] = {
            x: i * 300 + Math.floor(Math.random() * 80),
            width: 50 + Math.floor(Math.random() * 50),
          };
        }
        stones[0].x = 80;
        mode = "wait";
      }

      function animate() {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.fillText(
          "Distance remaining: " + (maxStones - currentStone - 1),
          250,
          100
        );
        stones.forEach((stone) => {
          context.fillRect(stone.x - offset, 398, stone.width, 600);
        });

        context.drawImage(
          image,
          Math.floor(frame) * size,
          0,
          size,
          size,
          x + size / 2,
          y,
          size,
          size
        );
        switch (mode) {
          case "pointerdown":
            stickLength++;
            break;
          case "stickFall":
            angle = angle + Math.PI / 64;
            if (angle >= 0) mode = "run";
            break;
          case "run":
            offset++;
            run++;
            frame = frame + 0.5;
            if (frame == 20) frame = 0;
            if (stickLength == run) {
              mode = "wait";
              angle = -Math.PI / 2;
              stickLength = 0;
              run = 0;
              let gameOver = true;
              stones.forEach((stone, index) => {
                if (
                  offset + x + size > stone.x &&
                  offset + x < stone.x + stone.width - size
                ) {
                  gameOver = false;
                  currentStone = Math.max(currentStone, index);
                  if (currentStone == maxStones - 1) {
                    mode = "gameOver";
                    frame = 21;
                  }
                }
              });
              if (gameOver) {
                mode = "gameOver";
                frame = 20;
              }
            }
            break;
          case "gameOver":
            if (currentStone < maxStones - 1) {
              y++;
              context.fillText("Game over. Click to restart", 20, 60);
            } else context.fillText("You win! Click to restart", 20, 60);
        }
        let x2 = x + (stickLength - run) * Math.cos(angle);
        let y2 = y + (stickLength - run) * Math.sin(angle);
        context.beginPath();
        context.moveTo(x + size - run, y + size);
        context.lineTo(x2 + size, y2 + size);
        context.stroke();
        window.requestAnimationFrame(animate);
      }

      window.onpointerdown = function () {
        switch (mode) {
          case "wait":
            mode = "pointerdown";
            break;
          case "gameOver":
            mode = "wait";
            reset();
        }
      };

      window.onpointerup = function () {
        if (mode == "pointerdown") mode = "stickFall";
      };
      reset();
      animate();
    </script>
  </body>
</html>
